import express from 'express';
import cors from 'cors';
import { Pool } from 'pg';
import dotenv from 'dotenv';

// Load environment variables
dotenv.config();

const app = express();
const port = process.env.PORT || 8085;

// Middleware
app.use(cors());
app.use(express.json());

// PostgreSQL connection
const pool = new Pool({
    user: process.env.DB_USER || 'wuzhao',
    host: process.env.DB_HOST || 'localhost',
    database: process.env.DB_NAME || 'wuzhao',
    password: process.env.DB_PASSWORD || 'wuzhao2025',
    port: parseInt(process.env.DB_PORT || '15432'),
});

// Initialize database tables
async function initDatabase() {
    try {
        const client = await pool.connect();

        // Create srs_callbacks table
        await client.query(`
      CREATE TABLE IF NOT EXISTS srs_callbacks (
        id SERIAL PRIMARY KEY,
        action VARCHAR(50) NOT NULL,
        client_id VARCHAR(100),
        ip VARCHAR(45),
        vhost VARCHAR(100),
        app VARCHAR(100),
        stream VARCHAR(100),
        param TEXT,
        server_id VARCHAR(100),
        stream_url VARCHAR(255),
        stream_id VARCHAR(100),
        tc_url VARCHAR(255),
        page_url VARCHAR(255),
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
      )
    `);

        // Create srs_heartbeats table
        await client.query(`
      CREATE TABLE IF NOT EXISTS srs_heartbeats (
        id SERIAL PRIMARY KEY,
        device_id VARCHAR(100),
        ip VARCHAR(45),
        summaries JSONB,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
      )
    `);

        client.release();
        console.log('Database tables initialized successfully');
    } catch (error) {
        console.error('Error initializing database:', error);
    }
}

// Generic callback handler
async function handleCallback(req: express.Request, res: express.Response, action: string) {
    try {
        const callbackData = req.body;
        console.log(`Received ${action} callback:`, callbackData);

        const client = await pool.connect();

        const query = `
      INSERT INTO srs_callbacks 
      (action, client_id, ip, vhost, app, stream, param, server_id, stream_url, stream_id, tc_url, page_url)
      VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
      RETURNING id
    `;

        const values = [
            action,
            callbackData.client_id,
            callbackData.ip,
            callbackData.vhost,
            callbackData.app,
            callbackData.stream,
            callbackData.param,
            callbackData.server_id,
            callbackData.stream_url,
            callbackData.stream_id,
            callbackData.tcUrl,
            callbackData.pageUrl
        ];

        const result = await client.query(query, values);
        client.release();

        console.log(`Stored ${action} callback with ID:`, result.rows[0].id);

        // Return success response as required by SRS
        res.status(200).json({ code: 0, msg: 'OK' });
    } catch (error) {
        console.error(`Error handling ${action} callback:`, error);
        res.status(500).json({ code: 1, msg: 'Internal server error' });
    }
}

// SRS Callback endpoints
app.post('/api/v1/streams', (req, res) => {
    const action = req.body.action;
    if (action === 'on_publish' || action === 'on_unpublish') {
        handleCallback(req, res, action);
    } else {
        res.status(400).json({ code: 1, msg: 'Invalid action' });
    }
});

app.post('/api/v1/sessions', (req, res) => {
    const action = req.body.action;
    if (action === 'on_play' || action === 'on_stop') {
        handleCallback(req, res, action);
    } else {
        res.status(400).json({ code: 1, msg: 'Invalid action' });
    }
});

app.post('/api/v1/dvrs', (req, res) => {
    handleCallback(req, res, 'on_dvr');
});

app.post('/api/v1/hls', (req, res) => {
    const action = req.body.action;
    if (action === 'on_hls' || action === 'on_hls_notify') {
        handleCallback(req, res, action);
    } else {
        res.status(400).json({ code: 1, msg: 'Invalid action' });
    }
});

// Heartbeat endpoint
app.post('/api/v1/servers', async (req, res) => {
    try {
        const heartbeatData = req.body;
        console.log('Received heartbeat:', heartbeatData);

        const client = await pool.connect();

        const query = `
      INSERT INTO srs_heartbeats 
      (device_id, ip, summaries)
      VALUES ($1, $2, $3)
      RETURNING id
    `;

        const values = [
            heartbeatData.device_id,
            heartbeatData.ip,
            heartbeatData.summaries ? JSON.stringify(heartbeatData.summaries) : null
        ];

        const result = await client.query(query, values);
        client.release();

        console.log('Stored heartbeat with ID:', result.rows[0].id);

        res.status(200).json({ code: 0, msg: 'OK' });
    } catch (error) {
        console.error('Error handling heartbeat:', error);
        res.status(500).json({ code: 1, msg: 'Internal server error' });
    }
});

// Health check endpoint
app.get('/health', (req, res) => {
    res.status(200).json({ status: 'OK', timestamp: new Date().toISOString() });
});

// Get callbacks endpoint (for debugging)
app.get('/api/v1/callbacks', async (req, res) => {
    try {
        const client = await pool.connect();
        const result = await client.query('SELECT * FROM srs_callbacks ORDER BY created_at DESC LIMIT 100');
        client.release();
        res.json(result.rows);
    } catch (error) {
        console.error('Error fetching callbacks:', error);
        res.status(500).json({ error: 'Internal server error' });
    }
});

// Get heartbeats endpoint (for debugging)
app.get('/api/v1/heartbeats', async (req, res) => {
    try {
        const client = await pool.connect();
        const result = await client.query('SELECT * FROM srs_heartbeats ORDER BY created_at DESC LIMIT 100');
        client.release();
        res.json(result.rows);
    } catch (error) {
        console.error('Error fetching heartbeats:', error);
        res.status(500).json({ error: 'Internal server error' });
    }
});

// Start server
async function startServer() {
    await initDatabase();

    app.listen(port, () => {
        console.log(`SRS Callback API server listening at port: ${port}`);
        console.log(`Health check: http://localhost:${port}/health`);
        console.log(`Callbacks endpoint: http://localhost:${port}/api/v1/callbacks`);
        console.log(`Heartbeats endpoint: http://localhost:${port}/api/v1/heartbeats`);
    });
}

startServer().catch(console.error);
